package com.cy.store.service.impl;

/**
 * @author Luo Sheng
 * @school YiBin university
 * @create 2022-11-23 16:43
 */

import com.cy.store.entity.User;
import com.cy.store.mapper.UserMapper;
import com.cy.store.service.BaseService;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.UUID;


/**
 * 用户模块业务层的实现类
 */
@Service
public class UserServiceImpl extends BaseService implements IUserService {
    @Autowired
    private UserMapper userMapper;

    /**
     * 用户注册具体实现方法
     * @param user
     */
    @Override
    public void reg(User user) {
        // 通过user参数来获取username
        String username = user.getUsername();

        // 调用findByUsername(username)判断用户是否注册过
        User result = userMapper.findByUsername(username);

        // 判断结果集是否为null，如果不为null则抛出用户名被占用异常
        if (!isNull(result)){
            // 抛出用户名被占用异常
            throw new UsernameDuplicatedException(USERNAME_ERROR_MESSAGE);

        }
        /**
         * 密码加密处理
         * 加密方式： 串 + password + 串 -> 连续加载三次
         * 串：盐值，盐值就是一个随机的字符串
         */
        // 获取未加密的password
        String oldPassword = user.getPassword();

        // 通过UUID来随机生成盐值并先记录盐值，以便用户登陆时判断
        String salt = UUID.randomUUID().toString();
        user.setSalt(salt);

        // 将密码和盐值作为一个整体进行加密处理，忽略原有密码的强度提升了数据的安全性
        String md5Password = getMD5Password(oldPassword, salt);
        user.setPassword(md5Password);

        // 补全数据：is_delete设置为0
        user.setIsDelete(NOT_DELETE);

        // 补全四个日志信息
        updateService(user,username,INSERT_DATA);

        // 执行业务注册功能的实现并返回row
        Integer row = userMapper.insert(user);

        // 判断如果row==1则代码执行成功，反之，抛出用户插入异常
        if (!row.equals(1)){
            throw new InsertException(INSERT_ERROR_MESSAGE);
        }
    }

    /**
     * 实现父接口中的抽象方法
     * @param user 用户名和密码
     * @return
     */
    @Override
    public User login(User user) {
        // 根据用户名称来查询用户信息是否存在，如果不存在就抛出异常
        User localUser = userMapper.findByUsername(user.getUsername());

        if (isNull(localUser)){
            // 抛出用户信息不存在异常
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);

        }
        // 检测用户密码是否匹配
        // 1、先获取数据库中的加密之后的密码
        String password = localUser.getPassword();

        // 2、和用户传递过来的密码进行比较
        // 2.1、先获取盐值
        String salt = localUser.getSalt();
        // 2.2、将用户密码按照相同的md5算法进行加密
        String md5Password = getMD5Password(user.getPassword(), salt);

        // 将加密后的密码与查询到的密码进行比较
        if (!password.equals(md5Password)){
            // 抛出用户密码错误异常
            throw new PasswordNotMatchException(PASSWORD_ERROR_MESSAGE);

        }
        // 判断is_delete的值是否为1，如果为1则抛出用户信息不存在异常
        if (localUser.getIsDelete().equals(IS_DELETE)){
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);

        }
        // 创建一个新的user对象，只保留原有对象的三个页面会用到的值，提升系统的性能
        User result = new User();
        result.setUid(localUser.getUid());
        result.setUsername(localUser.getUsername());
        result.setAvatar(localUser.getAvatar());
        return result;
    }

    /**
     * 更新用户密码
     * @param uid 用户id
     * @param username 用户名
     * @param oldPassword 老的密码
     * @param newPassword 新的密码
     */
    @Override
    public void changePassword(Integer uid,
                               String username,
                               String oldPassword,
                               String newPassword) {
        // 查询用户是否存在
        User result = userMapper.findByUid(uid);
        if (isNull(result) || result.getIsDelete().equals(IS_DELETE)){
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);
        }

        // 原始数据和数据库密码进行比较
        String oldMd5Password = getMD5Password(oldPassword,result.getSalt());
        if (!result.getPassword().equals(oldMd5Password)){
            throw new PasswordNotMatchException(PASSWORD_ERROR_MESSAGE);
        }

        // 将新的密码设置到数据库，将新的密码进行加密再去更新
        String newMd5Password = getMD5Password(newPassword, result.getSalt());

        // 更新密码
        Integer rows = userMapper.updatePasswordByUid(uid, newMd5Password, username, new Date());

        // 更新失败
        if (!rows.equals(1)){
            throw new UpdateException(UPDATE_ERROR_MESSAGE);
        }

    }

    /**
     * 根据用户id获取用户数据
     * @param uid 用户id
     * @return
     */
    @Override
    public User getByUid(Integer uid) {
        // 查询用户是否存在
        User result = userMapper.findByUid(uid);
        if (isNull(result) || result.getIsDelete().equals(IS_DELETE)){
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);
        }

        // 返回封装的user对象
        User user = new User();
        user.setPhone(result.getPhone());
        user.setUsername(result.getUsername());
        user.setGender(result.getGender());
        user.setEmail(result.getEmail());
        return user;
    }

    /**
     * 更新用户的信息
     * @param uid 用户的id
     * @param username 用户的名称
     * @param user 更新的数据
     */
    @Override
    public void changeInfo(Integer uid, String username, User user) {
        // 查询用户是否存在
        User result = userMapper.findByUid(uid);
        if (isNull(result) || result.getIsDelete().equals(IS_DELETE)){
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);
        }

        // 填补用户信息
        user.setUid(uid);
        updateService(user,username,UPDATE_DATA);

        // 调用更新方法
        Integer rows = userMapper.updateInfoByUid(user);
        if (!rows.equals(1)){
            throw new UpdateException(UPDATE_ERROR_MESSAGE);

        }


    }

    /**
     * 更新用户头像
     * @param uid 用户的Id
     * @param avatar 用户的头像路径
     * @param username 用户的名称
     */
    @Override
    public void changeAvatar(Integer uid, String avatar, String username) {
        // 查询当前的用户数据是否存在
        User result = userMapper.findByUid(uid);
        if (isNull(result) || result.getIsDelete().equals(IS_DELETE)){
            throw new UserNotFoundException(USER_NOTFOUND_MESSAGE);
        }

        // 调用Mapper方法更新用户头像
        Integer rows = userMapper.updateAvatarByUid(uid, avatar, username, new Date());
        if (!rows.equals(1)){
            throw new UpdateException(UPDATE_ERROR_MESSAGE);
        }
    }

}
